
#define MAX_PACKET (1400)
#define MAXWINDOW (500)
#define MAX_SEGMENT (MAX_PACKET - sizeof(struct lab6_header))

#define NORMAL ( 1 )
#define CLOSING ( 2 )
#define FIN_SENT ( 3 )



#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/time.h>
#include <sys/select.h>
#include <pthread.h>
#include <semaphore.h>

#define TIME_TO_WAIT (15000)

typedef pthread_mutex_t mutex;
typedef sem_t semaphore;

int nextSlot;
int startSlot;
int currentTimeout;
int currentRTT;
int currentVar;
int windowSize;


int recipientClosed;
int recvBase;
int receivedFin;
int sequenceNum;

int state;
int closed;

// Structure of the network header on the transmitted packet
struct lab6_header {
  uint32_t packet_num;
  uint32_t sequence_num;
  uint32_t ack_flag;
  uint16_t fin_flag;
  uint16_t length;

};


// Information about packets
typedef struct {
  
  char data[MAX_PACKET]; 
  int sequenceNumber;
  int length;
  int ack;
  int calculated; // Incorporated in timeout calculations yet?
  int sendTime;
  int recvTime;
  int timeout;

} packet;


/* Function for a sender thread that uses a shared buffer with the main
thread to manipulate sending multiple packets at once.

Nothing is returned; the argument passed in is the socket
*/
void * senderFunc( void * );

/* Send a packet out on the specified socket */
void sendPacket( int sock, packet * data );

/* Receive acks and mark appropriate packet as received */
int receiveAcks( int sock, int num );

/* Look through packets in the window, see what has been acked,
   and update the timeout, RTT, window base, and buffer status. 
   
   Update the appropriate semaphores and free sent packets */
void updateVariables( int localStartSlot, int sendNum );

/* Helper function to update the RTT and Var given send and receive times */
void updateTimeRTT( int, int );

/* Function for the user to receive data. Receives up to length bytes into
   the buffer in order; does not return until contiguous data are received. 
*/
int my_recv( int sock, void * buffer, size_t length );

/* Send an acknowledgement for a given packet header */
void send_ack( int sock, struct lab6_header * header );

/* Initialize a socket, along with other global state variabled */
int my_socket( int domain, int type, int protocol );

/* Interface function for the user to send data - adds data to the shared
   buffer. */
void my_send(int sock, void *buf, size_t len);

/* Closes the socket once all data have been sent, and cleans up before
   returning to the user. */
int my_close(int sock);

/* Misc functions for manipulating timevals, getting send state, and 
   connecting for the sender */

int timeval_to_msec(struct timeval *t) ;
void msec_to_timeval(int millis, struct timeval *out_timeval) ;
int current_msec() ;
int my_connect(int socket,struct sockaddr_in *toaddr,int addrsize) ;
int my_rtt(int sock) ;
int my_max_window(int sock) ;

/* Wrapper for malloc that checks return values */
void * Malloc( size_t );

